package com.enation.app.javashop.core.promotion.shetuan.service.impl;

import com.enation.app.javashop.core.base.CachePrefix;
import com.enation.app.javashop.core.client.goods.GoodsClient;
import com.enation.app.javashop.core.client.member.MemberAddressClient;
import com.enation.app.javashop.core.client.member.MemberClient;
import com.enation.app.javashop.core.goods.model.enums.GoodsType;
import com.enation.app.javashop.core.goods.model.vo.GoodsSkuVO;
import com.enation.app.javashop.core.goods.service.GoodsManager;
import com.enation.app.javashop.core.member.model.dos.LeaderDO;
import com.enation.app.javashop.core.member.model.dos.MemberAddress;
import com.enation.app.javashop.core.member.service.LeaderManager;
import com.enation.app.javashop.core.payment.model.enums.ClientType;
import com.enation.app.javashop.core.promotion.seckill.service.SeckillGoodsManager;
import com.enation.app.javashop.core.promotion.shetuan.exception.ShetuanErrorCode;
import com.enation.app.javashop.core.promotion.shetuan.service.ShetuanCartManager;
import com.enation.app.javashop.core.promotion.tool.model.dos.PromotionGoodsDO;
import com.enation.app.javashop.core.promotion.tool.model.enums.PromotionTypeEnum;
import com.enation.app.javashop.core.promotion.tool.model.vo.PromotionVO;
import com.enation.app.javashop.core.shop.model.dto.FixTimeSection;
import com.enation.app.javashop.core.shop.model.vo.ShopVO;
import com.enation.app.javashop.core.shop.service.ShopManager;
import com.enation.app.javashop.core.shop.service.impl.OrderReceiveTimeManager;
import com.enation.app.javashop.core.trade.TradeErrorCode;
import com.enation.app.javashop.core.trade.cart.model.enums.CartSourceType;
import com.enation.app.javashop.core.trade.cart.model.enums.CartType;
import com.enation.app.javashop.core.trade.cart.model.enums.CheckedWay;
import com.enation.app.javashop.core.trade.cart.model.vo.*;
import com.enation.app.javashop.core.trade.cart.service.CartPromotionManager;
import com.enation.app.javashop.core.trade.cart.service.cartbuilder.*;
import com.enation.app.javashop.core.trade.cart.service.cartbuilder.impl.CartSkuFilter;
import com.enation.app.javashop.core.trade.cart.service.cartbuilder.impl.DefaultCartBuilder;
import com.enation.app.javashop.core.trade.converter.TradePromotionConverter;
import com.enation.app.javashop.core.trade.order.model.dto.OrderDTO;
import com.enation.app.javashop.core.trade.order.model.enums.OrderStatusEnum;
import com.enation.app.javashop.core.trade.order.model.enums.OrderTypeEnum;
import com.enation.app.javashop.core.trade.order.model.enums.ShipTypeEnum;
import com.enation.app.javashop.core.trade.order.model.vo.CheckoutParamVO;
import com.enation.app.javashop.core.trade.order.model.vo.TradeVO;
import com.enation.app.javashop.core.trade.order.service.*;
import com.enation.app.javashop.core.trade.order.service.impl.DefaultTradeCreator;
import com.enation.app.javashop.framework.cache.Cache;
import com.enation.app.javashop.framework.context.UserContext;
import com.enation.app.javashop.framework.database.DaoSupport;
import com.enation.app.javashop.framework.exception.ServiceException;
import com.enation.app.javashop.framework.redis.transactional.RedisTransactional;
import com.enation.app.javashop.framework.security.model.Buyer;
import com.enation.app.javashop.framework.util.DateUtil;
import com.enation.app.javashop.framework.util.DictUtils;
import com.enation.app.javashop.framework.util.StringUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 社区团购物车操作
 */
@Service
public class ShetuanCartManagerImpl implements ShetuanCartManager {


    protected final Log logger = LogFactory.getLog(this.getClass());


    /**
     * 购物车促销渲染器
     */
    @Autowired
    private CartPromotionRuleRenderer cartPromotionRuleRenderer;

    /**
     * 购物车价格计算器
     */
    @Autowired
    private CartPriceCalculator cartPriceCalculator;

    /**
     * 购物车sku数据渲染器
     */
    @Autowired
    @Qualifier(value = "shetuanCartSkuRenderer")
    private CartSkuRenderer cartSkuRenderer;

    /**
     * 数据校验
     */
    @Autowired
    private CheckDataRebderer checkDataRebderer;

    /**
     * 购物车优惠券渲染器
     */
    @Autowired
    private CartCouponRenderer cartCouponRenderer;

    @Autowired
    private GoodsClient goodsClient;

    @Autowired
    protected TradeSnCreator tradeSnCreator;

    @Autowired
    protected CheckoutParamManager checkoutParamManager;

    @Autowired
    protected MemberClient memberClient;

    @Autowired
    protected MemberAddressClient memberAddressClient;

    @Autowired
    protected TradeIntodbManager tradeIntodbManager;

    @Autowired
    protected LeaderManager leaderManager;

    @Autowired
    private OrderReceiveTimeManager orderReceiveTimeManager;

    @Autowired
    private SeckillGoodsManager seckillGoodsManager;
    /**
     * 购物车运费价格计算器
     */
    @Autowired
    private CartShipPriceCalculator cartShipPriceCalculator;

    @Autowired
    private GoodsManager goodsManager;


    /**
     * 社区团购【购物车详情】
     * @param way  立即购买——BUY_NOW / 购车车下单——CART
     * @return
     */
    @Override
    public CartView getCartListAndCountPrice(CheckedWay way) {

        //调用CartView生产流程线进行生产
        CartBuilder cartBuilder = new DefaultCartBuilder(CartType.CART, cartSkuRenderer, cartPromotionRuleRenderer, cartPriceCalculator, checkDataRebderer);

        /**
         * 生产流程：渲染sku->校验sku是否有效->渲染促销规则->计算价格->生成成品
         * 生产流程说明 ： 校验sku是否有效必须放在渲染促销规则之前，如果参加满减活动的商品失效，那么满减活动无需渲染
         * update by liuyulei 2019-05-17
         */
        CartView cartView = cartBuilder
                .renderSku(way)
                .checkData()
                .renderPromotionRule(false, way)
                .countPrice()
                .build();
        List<CartVO> itemList = cartView.getCartList();
        processChecked(itemList);
        return cartView;
    }

    /**
     * 社区团购【结算详情】
     * @param way
     * @param sellerId
     * @return
     */
    @Override
    public CartView getCheckedItems( CheckedWay way,int sellerId) {

        //只有此卖家的商品才算数
        CartSkuFilter filter = (cartSkuVO) -> cartSkuVO.getSellerId().equals(sellerId);

        //调用CartView生产流程线进行生产(组建装配工厂) shetuanCartSkuRenderer
        CartBuilder cartBuilder = new DefaultCartBuilder(CartType.CHECKOUT, cartSkuRenderer, cartPromotionRuleRenderer, cartPriceCalculator, cartCouponRenderer,  cartShipPriceCalculator,checkDataRebderer);

        CartView cartView=cartBuilder.renderSku(filter,way).checkData().build();

        if(CollectionUtils.isEmpty(cartView.getCartList())){
            return cartView;
        }

        /**
         * 生产流程：渲染sku->校验sku是否有效->渲染促销规则(计算优惠券）->计算运费->计算价格 -> 渲染优惠券 ->生成成品
         * 生产流程说明 ： 校验sku是否有效必须放在渲染促销规则之前，如果参加满减活动的商品失效，那么满减活动无需渲染
         * 【renderSku】渲染购物车数据  --->>>> 【uniqueShipWay】可选配送方式  --->>>>【renderPromotionRule】核算促销   --->>>> 【countShipPrice】计算配送费用  --->>>> 【countPrice】  --->>>> 计算购物车总费用  --->>>>  【renderCoupon】 核算优惠券
         */

        //判断是否是虚拟商品，如果是虚拟商品则不用计算运费
        boolean isVirtual = goodsManager.checkVirtualGoods(cartView);

        if (isVirtual) {
            // 如果是虚拟商品，不用计算运费
            cartView = cartBuilder
                    .renderPromotionRule(true, way)
                    .countPrice()
                    .renderCoupon()
                    .build();
        } else {
            cartView = cartBuilder
                    .uniqueShipWay()
                    .renderPromotionRule(true, way)
                    .countShipPrice()
                    .countPrice()
                    .renderCoupon()
                    .build();
        }

        CartVO cartVO = cartView.getCartList().get(0);

        if(cartVO==null || CollectionUtils.isEmpty(cartVO.getSkuList())){
            logger.info("【购物车结算异常】");
            logger.info(UserContext.getBuyer().getUid()+"|"+way+"|"+sellerId);
        }
        if(cartVO!=null && cartVO.getAllowGlobal()==0){
            logger.info("【不支持快递到家】"+cartVO.getDispatchMsg());
        }

        return cartView;
    }

    /**
     * 社区团购【提交订单】
     * @param client
     * @param checkedWay
     * @param sellerId
     * @return
     */
    @Override
    @RedisTransactional(acquireTimeout = 1,lockTimeout = 30,lockName = "createTrade_",value = "#buyerId")
    public TradeVO createTrade(String client, CheckedWay checkedWay, int sellerId, Integer buyerId, double walletPayPrice,Integer receiveTimeSeq) {

        if (new Date().getHours() >= 23) {
            logger.error("超过晚上11点，不允许下单！");
            throw new ServiceException("1000", "商品活动配置中！");
        }

        this.setClientType(client);
        // 1 用户结算选择
        CheckoutParamVO param = checkoutParamManager.getParam();
        // 2 查看购物车
        CartView cartView = this.getCheckedItems(checkedWay,sellerId);
        if(CollectionUtils.isEmpty(cartView.getCartList())){
            logger.error("购物车已结算");
             throw new ServiceException("1000","购物车已结算,请刷新重试!");
        }
        // 3 用户默认地址
        MemberAddress memberAddress = this.memberAddressClient.getModel(param.getAddressId());

        // 4 查询团长信息
        String activeShipWay = cartView.getTotalPrice().getActiveShipWay();

        LeaderDO leaderDO = leaderManager.getLeaderDO(param, memberAddress, activeShipWay);

        // 5 组合1/2/3的参数
        TradeCreator tradeCreator = new DefaultTradeCreator(param,cartView,memberAddress).setTradeSnCreator( tradeSnCreator).setGoodsClient(goodsClient).setMemberClient(memberClient).setSeckillGoodsManager(seckillGoodsManager);

        //检测配置范围-> 检测商品合法性 -> 检测促销活动合法性 -> 创建交易
        TradeVO tradeVO = tradeCreator
                .checkGoods()
                .checkPromotion()
                .createTrade();

        // 获取用户指定配送时间
        FixTimeSection timeSection=orderReceiveTimeManager.getReceiveTimeBySeller(sellerId,receiveTimeSeq);
        // 中间处理社区团购订单信息
        List<OrderDTO> orderList = tradeVO.getOrderList();
        for (OrderDTO orderDTO : orderList) {
            orderDTO.setShippingType(activeShipWay);
            orderDTO.setOrderType(OrderTypeEnum.shetuan.name());
            if(activeShipWay.equals(ShipTypeEnum.SELF.name()) && leaderDO!=null){
                orderDTO.setLeaderId(leaderDO.getLeaderId());
                orderDTO.setPickAddr(leaderDO.getProvince()+leaderDO.getCity()+leaderDO.getTown()+leaderDO.getAddress());
            }
            orderDTO.setReceiveTime(timeSection.getReceiveTimeStamp());
            orderDTO.setReceiveTimeType(timeSection.getReceiveTimeType());
        }
        tradeVO.setCartSourceType(CartSourceType.SHETUAN_CART.name());
        tradeVO.setWalletPayPrice(walletPayPrice);
        //订单入库
        this.tradeIntodbManager.intoDB(tradeVO);

        return tradeVO;
    }

    /**
     * 设置client type
     * @param client
     */
    protected void setClientType(String client) {

        String clientType=null;
        if (StringUtil.isWap()) {
            clientType = ClientType.WAP.name();
        } else if (ClientType.REACT.getClient().equals(client)) {
            clientType = ClientType.REACT.getClient();
        }else{
            clientType = ClientType.PC.name();
        }

        this.checkoutParamManager.setClientType(clientType);
    }

    /**
     * 处理购物车的选中情况
     * 根据每个商品的选中情况来 设置店铺是否全选
     *
     * @param itemList
     */
    private void processChecked(List<CartVO> itemList) {
        for (CartVO cartVO : itemList) {
            //设置默认为店铺商品全选
            cartVO.setChecked(1);
            cartVO.setInvalid(0);

            //如果购物车有一个有效的商品
            Boolean notInvalid = false;

            for (CartSkuVO skuVO : cartVO.getSkuList()) {
                // 如果商品没有选中 并且他不是一个有效的商品
                if (skuVO.getChecked() == 0 && skuVO.getInvalid() == 0) {
                    cartVO.setChecked(0);
                }
                if (skuVO.getInvalid() == 0) {
                    notInvalid = true;
                }
            }

            //如果 所有商品都无效 && 购物车状态为以选中
            if (!notInvalid && cartVO.getChecked() == 1) {
                cartVO.setInvalid(1);
            }
            if (logger.isDebugEnabled()) {
                this.logger.info("购物车选中处理结果===》：");
                this.logger.info(cartVO.toString());
            }
        }
    }


}
